Skip to contentMethod: static {...}
1: /**
2: * Copyright (C) 2020 Czech Technical University in Prague
3: * <p>
4: * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
5: * License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later
6: * version.
7: * <p>
8: * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
9: * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
10: * details. You should have received a copy of the GNU General Public License along with this program. If not, see
11: * <http://www.gnu.org/licenses/>.
12: */
13: package cz.cvut.kbss.jopa.owl2java;
14:
15: import cz.cvut.kbss.jopa.owl2java.config.TransformationConfiguration;
16: import cz.cvut.kbss.jopa.owl2java.exception.OWL2JavaException;
17: import cz.cvut.kbss.jopa.util.MappingFileParser;
18: import org.semanticweb.owlapi.apibinding.OWLManager;
19: import org.semanticweb.owlapi.model.*;
20: import org.semanticweb.owlapi.search.EntitySearcher;
21: import org.semanticweb.owlapi.util.OWLOntologyMerger;
22: import org.slf4j.Logger;
23: import org.slf4j.LoggerFactory;
24:
25: import javax.annotation.Nonnull;
26: import java.io.File;
27: import java.net.URI;
28: import java.util.*;
29: import java.util.function.Consumer;
30: import java.util.stream.Stream;
31:
32: public class OWL2JavaTransformer {
33:
34: private static final Logger LOG = LoggerFactory.getLogger(OWL2JavaTransformer.class);
35:
36: private OWLOntology ontology;
37:
38: private final ValidContextAnnotationValueVisitor v = new ValidContextAnnotationValueVisitor();
39:
40: private final ContextDefinition defaultContext = new ContextDefinition();
41: private final Map<String, ContextDefinition> contexts = new HashMap<>();
42:
43: private boolean ignoreMissingImports;
44:
45: public Collection<String> listContexts() {
46: return contexts.keySet();
47: }
48:
49: public void ignoreMissingImports(boolean ignore) {
50: this.ignoreMissingImports = ignore;
51: }
52:
53: private OWLOntology getWholeOntology(final String owlOntologyName, final String mappingFile) {
54: // reader
55: final OWLOntologyManager m = OWLManager.createOWLOntologyManager();
56:
57: if (mappingFile != null) {
58: LOG.info("Using mapping file '{}'.", mappingFile);
59:
60: final Map<URI, URI> map = MappingFileParser.getMappings(new File(mappingFile));
61: m.getIRIMappers().add(ontologyIRI -> {
62: final URI value = map.get(ontologyIRI.toURI());
63:
64: if (value == null) {
65: return null;
66: } else {
67: return IRI.create(value);
68: }
69: });
70: LOG.info("Mapping file successfully parsed.");
71: }
72:
73: LOG.info("Loading ontology {}... ", owlOntologyName);
74: if (ignoreMissingImports) {
75: m.getOntologyConfigurator().setMissingImportHandlingStrategy(MissingImportHandlingStrategy.SILENT);
76: m.addMissingImportListener(e -> {
77: LOG.warn("Unable to import ontology {}.", e.getImportedOntologyURI());
78: LOG.debug("Error: {}", e.getCreationException().getMessage());
79: });
80: }
81:
82: try {
83: m.loadOntology(IRI.create(owlOntologyName));
84: return new OWLOntologyMerger(m).createMergedOntology(m, IRI.create(owlOntologyName + "-generated"));
85: } catch (OWLException | OWLRuntimeException e) {
86: LOG.error(e.getMessage(), e);
87: throw new OWL2JavaException("Unable to load ontology " + owlOntologyName, e);
88: }
89: }
90:
91: public void setOntology(final String owlOntologyName, final String mappingFile) {
92: this.ontology = getWholeOntology(owlOntologyName, mappingFile);
93:
94: LOG.debug("Parsing integrity constraints");
95:
96: ontology.axioms().forEach(a -> {
97: defaultContext.addAxiom(a);
98: for (final String icContextName : getContexts(a)) {
99: ContextDefinition ctx = getContextDefinition(icContextName);
100: ctx.addAxiom(a);
101: }
102: });
103: registerEntitiesInContexts();
104:
105: defaultContext.parse();
106: for (final ContextDefinition ctx : contexts.values()) {
107: ctx.parse();
108: }
109:
110: LOG.debug("Integrity constraints successfully parsed.");
111: }
112:
113: private void registerEntitiesInContexts() {
114: final Consumer<Stream<? extends OWLEntity>> consumer = stream -> stream.forEach(e -> {
115: defaultContext.add(e);
116: for (final String context : getContexts(e)) {
117: getContextDefinition(context).add(e);
118: }
119: });
120: consumer.accept(ontology.classesInSignature());
121: consumer.accept(ontology.objectPropertiesInSignature());
122: consumer.accept(ontology.dataPropertiesInSignature());
123: consumer.accept(ontology.annotationPropertiesInSignature());
124: }
125:
126: private ContextDefinition getContextDefinition(String icContextName) {
127: return contexts.computeIfAbsent(icContextName, name -> new ContextDefinition());
128: }
129:
130: private List<String> getContexts(final OWLAxiom a) {
131: final List<String> icContexts = new ArrayList<>();
132: a.annotations().filter(p -> p.getProperty().getIRI().toString().equals(Constants.P_IS_INTEGRITY_CONSTRAINT_FOR))
133: .forEach(p -> {
134: LOG.trace("Processing annotation : " + p);
135: p.getValue().accept(v);
136: final String icContextName = v.getName();
137: LOG.trace("CONTEXT:" + icContextName);
138: if (icContextName == null) {
139: return;
140: }
141: LOG.debug("Found IC {} for context {}", a, icContextName);
142: icContexts.add(icContextName);
143: });
144: return icContexts;
145: }
146:
147: private List<String> getContexts(final OWLEntity entity) {
148: final List<String> icContexts = new ArrayList<>();
149: EntitySearcher.getAnnotations(entity, ontology)
150: .filter(p -> p.getProperty().getIRI().toString().equals(Constants.P_IS_INTEGRITY_CONSTRAINT_FOR))
151: .forEach(p -> {
152: LOG.trace("Processing annotation : " + p);
153: p.getValue().accept(v);
154: final String icContextName = v.getName();
155: LOG.trace("CONTEXT:" + icContextName);
156: if (icContextName == null) {
157: return;
158: }
159: LOG.debug("Found OWLEntity declaration {} for context {}", entity, icContextName);
160: icContexts.add(icContextName);
161: });
162: return icContexts;
163: }
164:
165: private void verifyContextExistence(String context) {
166: if (!contexts.containsKey(context)) {
167: throw new IllegalArgumentException(
168: "Context " + context + " not found. Existing contexts: " + listContexts());
169: }
170: }
171:
172: public void transform(TransformationConfiguration transformConfig) {
173: final ContextDefinition def = getValidContext(transformConfig);
174: LOG.info("Transforming context ...");
175: final ObjectModel result = new JavaTransformer(transformConfig).generateModel(ontology, def);
176: result.writeModel(transformConfig.getTargetDir());
177: LOG.info("Transformation SUCCESSFUL.");
178: }
179:
180: private ContextDefinition getValidContext(TransformationConfiguration configuration) {
181: if (configuration.areAllAxiomsIntegrityConstraints()) {
182: LOG.info(" - for all axioms");
183: return defaultContext;
184: }
185: final String context = configuration.getContext();
186: verifyContextExistence(context);
187: LOG.info(" - for context '{}'.", context);
188: return contexts.get(context);
189: }
190:
191: /**
192: * Generates only vocabulary of the loaded ontology.
193: *
194: * @param transformConfig Configuration of the generation process
195: */
196: public void generateVocabulary(TransformationConfiguration transformConfig) {
197: LOG.info("Generating vocabulary ...");
198:
199: ContextDefinition def = getValidContext(transformConfig);
200: final ObjectModel result = new JavaTransformer(transformConfig).generateVocabulary(ontology, def);
201: result.writeModel(transformConfig.getTargetDir());
202: }
203:
204: private static class ValidContextAnnotationValueVisitor implements OWLAnnotationValueVisitor {
205:
206: private String name;
207:
208: String getName() {
209: return name;
210: }
211:
212: @Override
213: public void visit(@Nonnull OWLLiteral literal) {
214: this.name = literal.getLiteral();
215: }
216: }
217: }